home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / drivers.arc / 3C501.ASM next >
Encoding:
Assembly Source File  |  1988-10-20  |  12.3 KB  |  565 lines

  1. version    equ    3
  2.  
  3.     include    defs.asm    ;SEE ENCLOSED COPYRIGHT MESSAGE
  4.  
  5. ;Ported from Phil Karn's ec.c, a C-language driver for the 3COM 3C501
  6. ;by Russell Nelson.  Any bugs are due to Russell Nelson.
  7.  
  8. ;/* PC/FTP Packet Driver source, conforming to version 1.05 of the spec
  9. ;*  Portions (C) Copyright 1988 Phil Karn
  10. ;*
  11. ;*  Permission is granted to any individual or institution to use, copy,
  12. ;*  modify, or redistribute this software and its documentation provided
  13. ;*  this notice and the copyright notices are retained.  This software may
  14. ;*  not be distributed for profit, either in original form or in derivative
  15. ;*  works.  Phil Karn makes no representations about the suitability
  16. ;*  of this software for any purpose.  PHIL KARN GIVES NO WARRANTY,
  17. ;*  EITHER EXPRESS OR IMPLIED, FOR THE PROGRAM AND/OR DOCUMENTATION
  18. ;*  PROVIDED, INCLUDING, WITHOUT LIMITATION, WARRANTY OF MERCHANTABILITY
  19. ;*  AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE.
  20. ;*/
  21.  
  22. code    segment    byte public
  23.     assume    cs:code, ds:code
  24.  
  25. ;The various IE command registers
  26. EDLC_ADDR    equ    00h    ;EDLC station address, 6 bytes
  27. EDLC_RCV    equ    06h    ;EDLC receive csr
  28. EDLC_XMT    equ    07h    ;EDLC transmit csr
  29. IE_GP        equ    08h    ;GP pointer
  30. IE_RP        equ    0ah    ;Receive buffer pointer
  31. IE_SAPROM    equ    0ch    ;window on station addr prom
  32. IE_CSR        equ    0eh    ;IE command/status
  33. IE_BFR        equ    0fh    ;window on packet buffer
  34.  
  35. ;Bits in EDLC_RCV, interrupt enable on write, status when read
  36. EDLC_NONE    equ    000h    ;match mode in bits 5-6, write only
  37. EDLC_ALL    equ    040h    ;promiscuous receive, write only
  38. EDLC_BROAD    equ    080h    ;station address plus broadcast
  39. EDLC_MULTI    equ    0c0h    ;station address plus multicast
  40.  
  41. EDLC_STALE    equ    80h    ;receive CSR status previously read
  42. EDLC_GOOD    equ    20h    ;well formed packets only
  43. EDLC_ANY    equ    10h    ;any packet, even those with errors
  44. EDLC_SHORT    equ    08h    ;short frame
  45. EDLC_DRIBBLE    equ    04h    ;dribble error
  46. EDLC_FCS    equ    02h    ;CRC error
  47. EDLC_OVER    equ    01h    ;data overflow
  48.  
  49. EDLC_RERROR    equ    EDLC_SHORT or EDLC_DRIBBLE or EDLC_FCS or EDLC_OVER
  50. EDLC_RMASK    equ    EDLC_GOOD or EDLC_ANY or EDLC_RERROR
  51.  
  52. ;bits in EDLC_XMT, interrupt enable on write, status when read
  53. EDLC_IDLE    equ    08h    ;transmit idle
  54. EDLC_16        equ    04h    ;packet experienced 16 collisions
  55. EDLC_JAM    equ    02h    ;packet experienced a collision
  56. EDLC_UNDER    equ    01h    ;data underflow
  57.  
  58. ;bits in IE_CSR
  59. IE_RESET    equ    80h    ;reset the controller (wo)
  60. IE_XMTBSY    equ    80h    ;Transmitter busy (ro)
  61. IE_RIDE        equ    40h    ;request interrupt/DMA enable (rw)
  62. IE_DMA        equ    20h    ;DMA request (rw)
  63. IE_EDMA        equ    10h    ;DMA done (ro)
  64.  
  65. IE_BUFCTL    equ    0ch    ;mask for buffer control field (rw)
  66. IE_LOOP        equ    0ch    ;2 bit field in bits 2,3, loopback
  67. IE_RCVEDLC    equ    08h    ;gives buffer to receiver
  68. IE_XMTEDLC    equ    04h    ;gives buffer to transmit
  69. IE_SYSBFR    equ    00h    ;gives buffer to processor
  70.  
  71. IE_CRC        equ    01h    ;causes CRC error on transmit (wo)
  72. IE_RCVBSY    equ    01h    ;receive in progress (ro)
  73.  
  74. BFRSIZ        equ    2048    ;number of bytes in a buffer
  75.  
  76.     public    int_no
  77. int_no        db    3,0,0,0        ; interrupt number.
  78. io_addr        dw    0300h,0        ; I/O address for card (jumpers)
  79.  
  80.     public    driver_class, driver_type, driver_name
  81. driver_class    db    1        ;from the packet spec
  82. driver_type    db    1        ;from the packet spec
  83. driver_name    db    '3C501',0    ;name of the driver.
  84.  
  85. ipkt_size    dw    ?
  86. opkt_size    dw    ?
  87.  
  88. is_186        db    0        ;=0 if 808[68], =1 if 80[123]86.
  89. our_type    dw    ?
  90.  
  91.     public    send_pkt
  92. send_pkt:
  93. ;enter with ds:si -> packet, cx = packet length.
  94. ;exit with nc if ok, or else cy if error, dh set to error number.
  95.     assume    ds:nothing
  96.     cmp    cx,RUNT        ; minimum length for Ether
  97.     jae    oklen
  98.     mov    cx,RUNT        ; make sure size at least RUNT
  99. oklen:
  100.     inc    cx            ;round size up to next even number.
  101.     and    cx,not 1
  102.  
  103. ;Wait for transmitter ready, if necessary. IE_XMTBSY is valid
  104. ;only in the transmit mode, hence the initial check.
  105.  
  106.     loadport
  107.     setport    IE_CSR
  108.     in    al,dx
  109.     and    al,IE_BUFCTL
  110.     cmp    al,IE_XMTEDLC
  111.     jne    send_pkt_2
  112.  
  113.     mov    bx,20000        ;try this many times.
  114. send_pkt_3:
  115.     in    al,dx            ;if not busy, exit.
  116.     and    al,IE_XMTBSY
  117.     je    send_pkt_2
  118.     dec    bx
  119.     jne    send_pkt_3
  120.     mov    dh,CANT_SEND        ;timed out, can't send.
  121.     stc
  122.     ret
  123. send_pkt_2:
  124.  
  125. ;Get control of the board buffer and disable receiver
  126.     mov    al,IE_RIDE or IE_SYSBFR
  127.     setport    IE_CSR
  128.     out    dx,al
  129.  
  130. ;Point GP at beginning of packet
  131.     mov    ax,BFRSIZ
  132.     sub    ax,cx
  133.     setport    IE_GP
  134.     out    dx,ax
  135.  
  136.     setport    IE_BFR
  137.  
  138.     mov    opkt_size,cx    ; opkt_size = cx;
  139.     cmp    is_186,0    ; Can we use rep outsb?
  140.     je    out86        ; no - have to do it slowly.
  141.     rep    outsb
  142.     jmp    short ocnteven
  143. out86:
  144.     test    si,1        ; (buf & 1) ?
  145.     jz    obufeven    ; no
  146.     lodsb            ; al = *si++;
  147.     out    dx,al        ; out(dx,al);
  148.     dec    cx        ; cx--;
  149. obufeven:
  150.     mov    di,cx        ; save for later test
  151.     shr    cx,1        ; cx = cnt >> 1; (convert to word count)
  152. ; Do the bulk of the buffer, a word at a time
  153.     jcxz    onobuf        ; if(cx != 0){
  154. xb:    lodsw            ; do { ax = *si++; (si is word pointer)
  155.     out    dx,al        ; out(dx,lowbyte(ax));
  156.     mov    al,ah
  157.     out    dx,al        ; out(dx,hibyte(ax));
  158.     loop    xb        ; } while(--cx != 0); }
  159. ; now check for odd trailing byte
  160. onobuf:    shr    di,1        ; if (di & 1)
  161.     jnc    ocnteven
  162.     lodsb            ;   out(dx,*si++);
  163.     out    dx,al
  164. ocnteven:
  165.  
  166. ;Start transmitter
  167. ;Point GP at beginning of packet
  168.     mov    ax,BFRSIZ
  169.     sub    ax,opkt_size
  170.     setport    IE_GP
  171.     out    dx,ax
  172.  
  173.     mov    al,IE_RIDE or IE_XMTEDLC
  174.     setport    IE_CSR
  175.     out    dx,al
  176.  
  177.     ret
  178.  
  179.  
  180.     public    get_address
  181. get_address:
  182. ;get the address of the interface.
  183. ;enter with es:di -> place to get the address, cx = size of address buffer.
  184. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  185.     assume    ds:code
  186.     cmp    cx,6            ;make sure that we have enough room.
  187.     jb    get_address_2
  188.     mov    cx,6
  189.     xor    bx,bx
  190. get_address_1:
  191.     mov    ax,bx
  192.     loadport
  193.     setport    IE_GP
  194.     out    dx,ax
  195.  
  196.     setport    IE_SAPROM
  197.     in    al,dx
  198.     stosb
  199.     inc    bx
  200.     loop    get_address_1
  201.  
  202.     mov    cx,6
  203.     clc
  204.     ret
  205. get_address_2:
  206.     stc
  207.     ret
  208.  
  209.  
  210. ;Set Ethernet address on controller
  211. set_address:
  212. ;enter:
  213. ;    ds:si -> address
  214.  
  215.     loadport
  216.     setport    EDLC_ADDR
  217.     mov    cx,6
  218. set_address_1:
  219.     lodsb
  220.     out    dx,al
  221.     inc    dx
  222.     loop    set_address_1
  223.  
  224.     ret
  225.  
  226. terminate:
  227. ;Pulse IE_RESET
  228.     mov    al,IE_RESET
  229.     loadport
  230.     setport    IE_CSR
  231.     out    dx,al
  232.     mov    al,0
  233.     out    dx,al
  234.  
  235.     ret
  236.  
  237.  
  238.     public    reset_interface
  239. reset_interface:
  240. ;reset the interface.
  241. ;we don't do anything.
  242.     ret
  243.  
  244.  
  245. ;called when we want to determine what to do with a received packet.
  246. ;enter with cx = packet length, es:di -> packet type.
  247.     extrn    recv_find: near
  248.  
  249. ;called after we have copied the packet into the buffer.
  250. ;enter with ds:si ->the packet, cx = length of the packet.
  251.     extrn    recv_copy: near
  252.  
  253.     extrn    count_in_err: near
  254.     extrn    count_out_err: near
  255.  
  256.     public    recv
  257. recv:
  258. ;called from the recv isr.  All registers have been saved, and ds=cs.
  259. ;Upon exit, the interrupt will be acknowledged.
  260.     assume    ds:code
  261.  
  262. ;Check for transmit jam
  263.  
  264.     loadport
  265.     setport    IE_CSR
  266.     in    al,dx
  267.     and    al,IE_XMTBSY
  268.     jne    recv_isr_1
  269.  
  270.     setport    EDLC_XMT
  271.     in    al,dx
  272.     test    al,EDLC_16
  273.     je    recv_isr_2
  274. ;ecp->estats.jam16++;
  275.     call    rcv_fixup
  276.     jmp    short     recv_isr_3
  277. recv_isr_2:
  278.     test    al,EDLC_JAM
  279.     je    recv_isr_3
  280. ;Crank counter back to beginning and restart transmit
  281. ;ecp->estats.jam++;
  282.     mov    al,IE_RIDE or IE_SYSBFR
  283.     setport    IE_CSR
  284.     out    dx,al
  285.  
  286.     mov    ax,BFRSIZ
  287.     sub    ax,opkt_size
  288.     setport    IE_GP
  289.     out    dx,ax
  290.  
  291.     mov    al,IE_RIDE or IE_XMTEDLC
  292.     setport    IE_CSR
  293.     out    dx,al
  294.  
  295. recv_isr_3:
  296.  
  297. recv_isr_1:
  298.     loadport
  299.     setport    EDLC_RCV
  300.     in    al,dx
  301.     test    al,EDLC_STALE
  302.     jne    recv_isr_4_j_1
  303.     test    al,EDLC_OVER
  304.     je    recv_isr_5
  305. ;ecp->estats.over++;
  306.     call    rcv_fixup
  307.     jmp    recv_isr_1
  308. recv_isr_5:
  309.     test    al,EDLC_SHORT or EDLC_FCS or EDLC_DRIBBLE
  310.     je    recv_isr_6
  311. ;ecp->estats.bad++;
  312.     call    rcv_fixup
  313.     jmp    recv_isr_1
  314. recv_isr_4_j_1:
  315.     jmp    recv_isr_4
  316. recv_isr_6:
  317.     test    al,EDLC_ANY
  318.     je    recv_isr_4_j_1
  319. ;Get control of the buffer
  320.     mov    al,IE_RIDE or IE_SYSBFR
  321.     setport    IE_CSR
  322.     out    dx,al
  323.  
  324.     setport    IE_RP
  325.     in    ax,dx            ;get the size.
  326.     mov    ipkt_size,ax
  327.     cmp    ax,RUNT            ;less than RUNT?
  328.     jb    recv_isr_7        ;yes.
  329.     cmp    ax,GIANT        ;greater than GIANT?
  330.     jbe    recv_isr_8        ;no.
  331. recv_isr_7:
  332.     call    count_in_err
  333. ;ecp->estats.bad++;
  334.     jmp    recv_isr_9
  335. recv_isr_8:
  336. ;Put it on the receive queue
  337.  
  338.     mov    ax,6+6            ;seek to the type word.
  339.     setport    IE_GP
  340.     out    dx,ax
  341.  
  342.     setport    IE_BFR
  343.     in    al,dx            ;read the type word out of the board.
  344.     mov    ah,al
  345.     in    al,dx
  346.     xchg    al,ah            ;should be in network byte order.
  347.     mov    our_type,ax
  348.  
  349.     mov    ax,ds            ;look up our type.
  350.     mov    es,ax
  351.     mov    di,offset our_type
  352.     mov    cx,ipkt_size
  353.     call    recv_find
  354.  
  355.     mov    ax,es            ;is this pointer null?
  356.     or    ax,di
  357.     je    recv_isr_9        ;yes - just free the frame.
  358.  
  359.     push    es            ;remember where the buffer pointer is.
  360.     push    di
  361.  
  362.     xor    ax,ax            ;seek to the beginning again.
  363.     loadport
  364.     setport    IE_GP
  365.     out    dx,ax
  366.  
  367.     mov    cx,ipkt_size
  368.     setport    IE_BFR
  369.  
  370.     cmp    is_186,0    ; Can we use rep insb?
  371.     je    in86        ; no - have to do it slowly.
  372.     rep    insb
  373.     jmp    short icnteven
  374. in86:
  375. ; If buffer doesn't begin on a word boundary, get the first byte
  376.     test    di,1    ; if(buf & 1){
  377.     jz    ibufeven ;
  378.     in    al,dx    ; al = in(dx);
  379.     stosb        ; *di++ = al
  380.     dec    cx    ; cx--;
  381. ibufeven:
  382.     mov    si,cx    ; size = cx;
  383.     shr    cx,1    ; cx = cnt >> 1; (convert to word count)
  384. ; Do the bulk of the buffer, a word at a time
  385.     jcxz    inobuf    ; if(cx != 0){
  386. rb:    in    al,dx    ; do { al = in(dx);
  387.     mov    ah,al
  388.     in    al,dx    ; ah = in(dx);
  389.     xchg    al,ah
  390.     stosw        ; *si++ = ax; (di is word pointer)
  391.     loop    rb    ; } while(--cx != 0);
  392. ; now check for odd trailing byte
  393. inobuf:    shr    si,1
  394.     jnc    icnteven
  395.     in    al,dx
  396.     stosb        ; *di++ = al
  397. icnteven:
  398.  
  399.     pop    si
  400.     pop    ds
  401.     assume    ds:nothing
  402.     mov    cx,ipkt_size
  403.     call    recv_copy        ;tell them that we copied it.
  404.  
  405.     mov    ax,cs            ;restore our ds.
  406.     mov    ds,ax
  407.     assume    ds:code
  408.  
  409. recv_isr_9:
  410.     mov    al,IE_RIDE or IE_RCVEDLC
  411.     loadport
  412.     setport    IE_CSR
  413.     out    dx,al
  414.     xor    al,al
  415.     setport    IE_RP
  416.     out    dx,al
  417. recv_isr_4:
  418. ;Clear any spurious interrupts
  419.     loadport
  420.     setport    EDLC_RCV
  421.     in    al,dx
  422.  
  423.     setport    EDLC_XMT
  424.     in    al,dx
  425.  
  426.     ret
  427.  
  428.  
  429. rcv_fixup:
  430.     call    count_out_err
  431.  
  432.     mov    al,IE_RIDE or IE_SYSBFR
  433.     loadport
  434.     setport    IE_CSR
  435.     out    dx,al
  436.  
  437.     mov    al,IE_RIDE or IE_RCVEDLC
  438.     setport    IE_CSR
  439.     out    dx,al
  440.  
  441.     mov    al,0
  442.     setport    IE_RP
  443.     out    dx,al
  444.  
  445.     ret
  446.  
  447.  
  448. end_resident    label    byte
  449.  
  450.     public    usage_msg
  451. usage_msg    db    "usage: 3C501 <packet_int_no> <int_no> <io_addr>",CR,LF,'$'
  452.  
  453.     public    copyright_msg
  454. copyright_msg    db    "Packet driver for the 3COM 3C501, version ",'0'+version,CR,LF
  455.         db    "Portions Copyright 1988 Phil Karn",CR,LF,'$'
  456.  
  457. using_186_msg    db    "Using 80[123]86 I/O instructions.",CR,LF,'$'
  458. no_3c501_msg    db    "No 3C501 found at that address.",CR,LF,'$'
  459. ether_bdcst    db    6 dup(-1)    ;ethernet broadcast address.
  460. our_address    db    6 dup(?)    ;temporarily hold our address
  461.  
  462. int_no_name    db    "Interrupt number ",'$'
  463. io_addr_name    db    "I/O port ",'$'
  464.  
  465.     extrn    set_recv_isr: near
  466.  
  467. ;enter with si -> argument string, di -> word to store.
  468. ;if there is no number, don't change the number.
  469.     extrn    get_number: near
  470.  
  471.     public    parse_args
  472. parse_args:
  473.     mov    di,offset int_no
  474.     mov    bx,offset int_no_name
  475.     call    get_number
  476.     mov    di,offset io_addr
  477.     mov    bx,offset io_addr_name
  478.     call    get_number
  479.     ret
  480.  
  481.  
  482. no_3c501_error:
  483.     mov    dx,offset no_3c501_msg
  484.     mov    ah,9
  485.     int    21h
  486.     stc
  487.     ret
  488.  
  489.  
  490.     public    etopen
  491. etopen:
  492. ;  Initialize the Ethernet board, set receive type.
  493. ;
  494. ;  check for correct EPROM location
  495. ;
  496. ;Pulse IE_RESET
  497.     mov    al,IE_RESET
  498.     loadport
  499.     setport    IE_CSR
  500.     out    dx,al
  501.  
  502. ;Determine the processor type.  The 8088 and 8086 will actually shift ax
  503. ;over by 33 bits, while the 80[123]86 use a shift count mod 32.
  504.     mov    cl,33
  505.     mov    ax,0ffffh
  506.     shl    ax,cl
  507.     jz    not_186
  508.     mov    is_186,1
  509.     mov    dx,offset using_186_msg
  510.     mov    ah,9
  511.     int    21h
  512. not_186:
  513.  
  514.     call    set_recv_isr
  515.  
  516.     push    ds
  517.     pop    es
  518.     mov    di,offset our_address
  519.     mov    cx,6
  520.     call    get_address
  521.     mov    si,offset our_address
  522.     call    set_address
  523.  
  524. ;See if there really is a 3c501 there.
  525.     mov    cx,6
  526.     mov    di,offset ether_bdcst
  527.     repe    cmpsb
  528.     jne    have_3c501        ;not broadcast address -- must be real.
  529.     jmp    no_3c501_error        ;not there -- no 3c501.
  530. have_3c501:
  531.  
  532. ;Enable DMA/interrupt request, gain control of buffer
  533.     mov    al,IE_RIDE or IE_SYSBFR
  534.     loadport
  535.     setport    IE_CSR
  536.     out    dx,al
  537.  
  538. ;Enable transmit interrupts
  539.     mov    al,EDLC_16 or EDLC_JAM
  540.     setport    EDLC_XMT
  541.     out    dx,al
  542.  
  543. ;Set up the receiver interrupts and flush status
  544.     mov    al,EDLC_MULTI or EDLC_GOOD or EDLC_ANY or EDLC_SHORT or EDLC_DRIBBLE or EDLC_FCS or EDLC_OVER
  545.     setport    EDLC_RCV
  546.     out    dx,al
  547.     in    al,dx            ;flush status.
  548.  
  549. ;Start receiver
  550.     mov    ax,0            ;Reset read pointer
  551.     setport    IE_RP
  552.     out    dx,ax
  553.     mov    al,IE_RIDE or IE_RCVEDLC
  554.     setport    IE_CSR
  555.     out    dx,al
  556.  
  557.     mov    dx,offset end_resident
  558.     clc
  559.     ret
  560.  
  561.  
  562. code    ends
  563.  
  564.     end
  565.